package com.echovin.esb.gateway.filter;

import com.echovin.esb.gateway.constants.ErrorCode;
import com.echovin.esb.gateway.constants.OrderConstants;
import com.echovin.esb.gateway.exception.OpenException;
import com.echovin.esb.gateway.oauth2.handler.OAuth2AccessDecisionManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;

/**
 * token校验过滤器
 */
@Component
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config>  {
    private static final String DATETIME_KEY = "headerName";
    @Autowired
    OAuth2AccessDecisionManager manager;

    public TokenGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(DATETIME_KEY);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return new OrderedGatewayFilter((exchange, chain) -> {
            //判断header里有放token
            ServerHttpRequest request = exchange.getRequest();
            HttpHeaders headers = exchange.getRequest().getHeaders();
            String token = headers.getFirst(config.getHeaderName());
            String url = request.getURI().getPath();
            if (!StringUtils.isEmpty(headers.getFirst("SOAPAction"))) {
                // 说明是webservice，对其动作进行权限校验
                url = headers.getFirst("SOAPAction");
            }
            // 判断当前操作是否在列表中，无权限则返回提示页面
            boolean hasPermission = manager.checkPermission(token, url, null);
            if (!hasPermission) {
                throw new OpenException(ErrorCode.INVALID_TOKEN.getCode());
            }
            return chain.filter(exchange);

        }, OrderConstants.TOKEN_AUTHORIZE);
    }

    public static class Config {
        /**
         * 传输token header key
         */
        private String headerName;

        public String getHeaderName() {
            return headerName;
        }

        public void setHeaderName(String headerName) {
            this.headerName = headerName;
        }
    }

}
